package com.itheima.service.db.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.domain.db.AnalysisByDay;
import com.itheima.domain.db.Analysis;
import com.itheima.mapper.AnalysisByDayMapper;
import com.itheima.mapper.LogMapper;
import com.itheima.service.db.AnalysisByDayService;
import com.itheima.util.ComputeUtil;
import com.itheima.util.DateFormatUtil;
import com.itheima.vo.AnalysisSummaryVo;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.*;

@Service
public class AnalysisByDayServiceImpl implements AnalysisByDayService {

    @Autowired
    private LogMapper logMapper;

    @Autowired
    private AnalysisByDayMapper analysisByDayMapper;

    //分析日志表,生成分析表数据
    @Override
    public void analysis() {
        //1. 确定今天 昨天两个日期
        Date date = new Date();
        String today = DateUtil.offsetDay(date, 0).toDateStr();
        String yesterday = DateUtil.offsetDay(date, -1).toDateStr();

        //2. 调用mapper生成四个值
        Integer numRegistered = logMapper.countByTypeAndTime("0102", today);//新注册用户数
        Integer numActive = logMapper.countByTime(today);//活跃用户数
        Integer numLogin = logMapper.countByTypeAndTime("0101", today);//登录次数
        Integer numRetention1d = logMapper.keep(yesterday, today);//次日留存用户数

        //3. 向分析表中写入数据
        //3-1 先根据日期查询,是否存在记录
        QueryWrapper<AnalysisByDay> wrapper = new QueryWrapper<>();
        wrapper.eq("record_date", today);
        AnalysisByDay analysisByDay = analysisByDayMapper.selectOne(wrapper);

        if (analysisByDay == null) {
            //3-2 如果不存在,新增一条记录
            analysisByDay = new AnalysisByDay();
            analysisByDay.setRecordDate(new Date());//日期
            analysisByDay.setNumRegistered(numRegistered);//新注册用户数
            analysisByDay.setNumActive(numActive);//活跃用户数
            analysisByDay.setNumLogin(numLogin);//登录次数
            analysisByDay.setNumRetention1d(numRetention1d);//次日留存用户数
            analysisByDayMapper.insert(analysisByDay);
        } else {
            //3-3 如果存在,更新这条记录
            analysisByDay.setNumRegistered(numRegistered);//新注册用户数
            analysisByDay.setNumActive(numActive);//活跃用户数
            analysisByDay.setNumLogin(numLogin);//登录次数
            analysisByDay.setNumRetention1d(numRetention1d);//次日留存用户数
            analysisByDayMapper.updateById(analysisByDay);
        }
    }

    //统计展示
    @Override
    public AnalysisSummaryVo summary() {
        //0-1 基础准备
        AnalysisSummaryVo analysisSummaryVo = new AnalysisSummaryVo();
        Date date = new Date();
        String today = DateUtil.offsetDay(date, 0).toDateStr();
        String yesterday = DateUtil.offsetDay(date, -1).toDateStr();
        String today_30 = DateUtil.offsetDay(date, -30).toDateStr();
        String today_7 = DateUtil.offsetDay(date, -7).toDateStr();

        //0-2 今日数据
        QueryWrapper<AnalysisByDay> wrapper = new QueryWrapper<>();
        wrapper.eq("record_date", today);
        AnalysisByDay todayAnalysisByDay = analysisByDayMapper.selectOne(wrapper);

        //0-3 昨日数据
        QueryWrapper<AnalysisByDay> wrapper1 = new QueryWrapper<>();
        wrapper1.eq("record_date", yesterday);
        AnalysisByDay yesterdayAnalysisByDay = analysisByDayMapper.selectOne(wrapper1);


        //累计用户数(每天注册用户数之和)
        Long cumulativeUsers = analysisByDayMapper.findAllRegisterNum();
        analysisSummaryVo.setCumulativeUsers(cumulativeUsers);

        //过去30天活跃用户数
        Long activePassMonth = analysisByDayMapper.findActiveUserNum(today_30, today);
        analysisSummaryVo.setActivePassMonth(activePassMonth);

        //过去7天活跃用户
        Long activePassWeek = analysisByDayMapper.findActiveUserNum(today_7, today);
        analysisSummaryVo.setActivePassWeek(activePassWeek);


        //今日新增用户数量
        Long newUsersToday = todayAnalysisByDay.getNumRegistered().longValue();
        analysisSummaryVo.setNewUsersToday(newUsersToday);


        //今日新增用户涨跌率，单位百分数，正数为涨，负数为跌   BigDecimal : 商业数字格式
        BigDecimal newUsersTodayRate = ComputeUtil.
                computeRate(todayAnalysisByDay.getNumRegistered(), yesterdayAnalysisByDay.getNumRegistered());
        analysisSummaryVo.setNewUsersTodayRate(newUsersTodayRate);

        //今日登录次数
        Long loginTimesToday = todayAnalysisByDay.getNumLogin().longValue();
        analysisSummaryVo.setLoginTimesToday(loginTimesToday);


        //今日登录次数涨跌率，单位百分数，正数为涨，负数为跌
        BigDecimal loginTimesTodayRate =
                ComputeUtil.computeRate(todayAnalysisByDay.getNumLogin(), yesterdayAnalysisByDay.getNumLogin());
        analysisSummaryVo.setLoginTimesTodayRate(loginTimesTodayRate);

        //今日活跃用户数量
        Long activeUsersToday = todayAnalysisByDay.getNumActive().longValue();
        analysisSummaryVo.setActiveUsersToday(activeUsersToday);

        //今日活跃用户涨跌率，单位百分数，正数为涨，负数为跌
        BigDecimal activeUsersTodayRate =
                ComputeUtil.computeRate(todayAnalysisByDay.getNumActive(), yesterdayAnalysisByDay.getNumActive());
        analysisSummaryVo.setActiveUsersTodayRate(activeUsersTodayRate);

        return analysisSummaryVo;
    }

    //分析图
    @Override
    public Map analysisSummary(Long sd, Long ed, String type) {
        //转化为date
        Date dateStrart = new Date(sd);
        Date dateStrart2 = DateUtil.offset(dateStrart, DateField.YEAR,-1);//去年
        Date dateEnd = new Date(ed);
        Date dateEnd2  = DateUtil.offset(dateEnd, DateField.YEAR,-1);//去年

        Map<String, List<Analysis>> map = new HashMap<>();
        List<Analysis> list = new ArrayList<>();
        List<Analysis> list2 = new ArrayList<>();//去年
        String end = DateUtil.offsetDay(dateEnd, 0).toDateStr();
        String end2 = DateUtil.offsetDay(dateEnd2, 0).toDateStr();//去年
        int i = 0;
        while(true){
            String start = DateUtil.offsetDay(dateStrart, i).toDateStr();
            String start2 = DateUtil.offsetDay(dateStrart2, i).toDateStr();//去年
            QueryWrapper<AnalysisByDay> wrapper = new QueryWrapper<>();
            QueryWrapper<AnalysisByDay> wrapper2 = new QueryWrapper<>();
            wrapper.eq("record_date", start);
            wrapper2.eq("record_date", start2);//去年
            AnalysisByDay todayAnalysisByDay = analysisByDayMapper.selectOne(wrapper);
            AnalysisByDay todayAnalysisByDay2 = analysisByDayMapper.selectOne(wrapper2);
            Analysis analysis= new Analysis();
            Analysis analysis2= new Analysis();//去年
            if(type.equals("101")){//新增
                Integer numRegistered = todayAnalysisByDay.getNumRegistered();
                Integer numRegistered2 = todayAnalysisByDay2.getNumRegistered();
                analysis.setAmount(numRegistered);//设置新增数量
                analysis2.setAmount(numRegistered2);//去年
                analysis.setTitle(start);//设置日期
                analysis2.setTitle(start2);//去年
            }else if(type.equals("102")){//活跃用户
                Integer numActive = todayAnalysisByDay.getNumActive();
                Integer numActive2 = todayAnalysisByDay2.getNumActive();
                analysis.setAmount(numActive);
                analysis2.setAmount(numActive2);//去年
                analysis.setTitle(start);
                analysis2.setTitle(start2);//去年
            }else{//次日留存率
                Integer numRetention1d = todayAnalysisByDay.getNumRetention1d();
                Integer numRetention1d2 = todayAnalysisByDay2.getNumRetention1d();
                analysis.setAmount(numRetention1d);
                analysis2.setAmount(numRetention1d2);//去年
                analysis.setTitle(start);
                analysis2.setTitle(start2);//去年
            }
             i++;
            list.add(analysis);
            list2.add(analysis2);//去年
            if(start.equals(end)){
                break;
            }
            if(start2.equals(end2)){
                break;
            }
        }
        map.put("thisYear",list);
        map.put("lastYear",list2);//去年
        return map;
    }
}